<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <h2>一、Observable 是什么</h2>
  <div>Vue.observable，让一个对象变成响应式数据。Vue 内部会用它来处理 data 函数返回的对象</div>
  <br>
  <div>返回的对象可以直接用于渲染函数和计算属性内，并且会在发生变更时触发相应的更新。也可以作为最小化的跨组件状态存储器</div>
  <h2>二、使用场景</h2>
  <div>在非父子组件通信时，可以使用通常的bus或者使用vuex，但是实现的功能不是太复杂，而使用上面两个又有点繁琐。这时，observable就是一个很好的选择</div>
  <script>
    // 创建一个js文件
    // 引入vue
    // import Vue from 'vue
    // // 创建state对象，使用observable让state对象可响应
    // export let state = Vue.observable({
    //   name: '张三',
    //   'age': 38
    // })
    // // 创建对应的方法
    // export let mutations = {
    //   changeName(name) {
    //     state.name = name
    //   },
    //   setAge(age) {
    //     state.age = age
    //   }
    // }

    // 在.vue文件中直接使用即可
    // <template>
    //   <div>
    //     姓名：{{ name }}
    //     年龄：{{ age }}
    //     <button @click="changeName('李四')">改变姓名</button>
    //     <button @click="setAge(18)">改变年龄</button>
    //   </div>
    // </template>
    // import { state, mutations } from '@/store
    // export default {
    //   // 在计算属性中拿到值
    //   computed: {
    //     name() {
    //       return state.name
    //     },
    //     age() {
    //       return state.age
    //     }
    //   },
    //   // 调用mutations里面的方法，更新数据
    //   methods: {
    //     changeName: mutations.changeName,
    //     setAge: mutations.setAge
    //   }
    // }
  </script>
  <h2>三、原理分析</h2>
  <script>
    // export function observe (value: any, asRootData: ?boolean): Observer | void {
    //   if (!isObject(value) || value instanceof VNode) {
    //     return
    //   }
    //   let ob: Observer | void
    //   // 判断是否存在__ob__响应式属性
    //   if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {
    //     ob = value.__ob__
    //   } else if (
    //     shouldObserve &&
    //     !isServerRendering() &&
    //     (Array.isArray(value) || isPlainObject(value)) &&
    //     Object.isExtensible(value) &&
    //     !value._isVue
    //   ) {
    //     // 实例化Observer响应式对象
    //     ob = new Observer(value)
    //   }
    //   if (asRootData && ob) {
    //     ob.vmCount++
    //   }
    //   return ob
    // }

    // Observer类
    // export class Observer {
    //     value: any;
    //     dep: Dep;
    //     vmCount: number; // number of vms that have this object as root $data

    //     constructor (value: any) {
    //         this.value = value
    //         this.dep = new Dep()
    //         this.vmCount = 0
    //         def(value, '__ob__', this)
    //         if (Array.isArray(value)) {
    //             if (hasProto) {
    //                 protoAugment(value, arrayMethods)
    //             } else {
    //                 copyAugment(value, arrayMethods, arrayKeys)
    //             }
    //             this.observeArray(value)
    //         } else {
    //             // 实例化对象是一个对象，进入walk方法
    //             this.walk(value)
    //         }
    // }

    // walk函数
    // walk (obj: Object) {
    //     const keys = Object.keys(obj)
    //     // 遍历key，通过defineReactive创建响应式对象
    //     for (let i = 0; i < keys.length; i++) {
    //         defineReactive(obj, keys[i])
    //     }
    // }

    // defineReactive方法
    // export function defineReactive (
    //   obj: Object,
    //   key: string,
    //   val: any,
    //   customSetter?: ?Function,
    //   shallow?: boolean
    // ) {
    //   const dep = new Dep()

    //   const property = Object.getOwnPropertyDescriptor(obj, key)
    //   if (property && property.configurable === false) {
    //     return
    //   }

    //   // cater for pre-defined getter/setters
    //   const getter = property && property.get
    //   const setter = property && property.set
    //   if ((!getter || setter) && arguments.length === 2) {
    //     val = obj[key]
    //   }

    //   let childOb = !shallow && observe(val)
    //   // 接下来调用Object.defineProperty()给对象定义响应式属性
    //   Object.defineProperty(obj, key, {
    //     enumerable: true,
    //     configurable: true,
    //     get: function reactiveGetter () {
    //       const value = getter ? getter.call(obj) : val
    //       if (Dep.target) {
    //         dep.depend()
    //         if (childOb) {
    //           childOb.dep.depend()
    //           if (Array.isArray(value)) {
    //             dependArray(value)
    //           }
    //         }
    //       }
    //       return value
    //     },
    //     set: function reactiveSetter (newVal) {
    //       const value = getter ? getter.call(obj) : val
    //       /* eslint-disable no-self-compare */
    //       if (newVal === value || (newVal !== newVal && value !== value)) {
    //         return
    //       }
    //       /* eslint-enable no-self-compare */
    //       if (process.env.NODE_ENV !== 'production' && customSetter) {
    //         customSetter()
    //       }
    //       // #7981: for accessor properties without setter
    //       if (getter && !setter) return
    //       if (setter) {
    //         setter.call(obj, newVal)
    //       } else {
    //         val = newVal
    //       }
    //       childOb = !shallow && observe(newVal)
    //       // 对观察者watchers进行通知,state就成了全局响应式对象
    //       dep.notify()
    //     }
    //   })
    // }
  </script>
</body>
</html>